package com.putao.web.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.putao.annotation.OperateMethodName;
import com.putao.base.BaseController;
import com.putao.base.BaseWrapper;
import com.putao.constants.Constants;
import com.putao.domain.Account;
import com.putao.domain.Bill;
import com.putao.result.JsonResult;
import com.putao.service.AccountService;
import com.putao.service.BillService;
import com.putao.utils.BigDecimalUtil;
import com.putao.utils.RequestUtils;
import com.putao.utils.StringUtils;
import com.putao.utils.ThreadLocalUtil;
import com.putao.vo.AccountBillVo;
import com.putao.vo.AccountVo;
import com.putao.vo.BaseVo;
import com.putao.web.controller.vo.account.AccountOtherVo;
import com.putao.web.controller.vo.account.AccountResultVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author fuhehuang
 * @email 2628279194@qq.com
 */
@Api(tags = {"9.0 账户增删改查类"})
@RestController
@RequestMapping("/accounts")
@Slf4j
public class AccountController extends BaseController<Account> {

    @Autowired
    private AccountService accountService;
    @Autowired
    private BillService billService;

    /**
     * 账户列表
     *
     * @return
     */
    @GetMapping
//    @RequiresRoles(value={"admin"})
    @ApiOperation(value = "账户列表", notes = "base对象")
    @OperateMethodName(value = "账户列表", method = "account:list")
    public JsonResult list(HttpServletRequest request, BaseVo baseVo) {
        String env = RequestUtils.getEnv(request);
        String userId = ThreadLocalUtil.getUserId();
        if (BaseVo.ENV_PHONE.equals(env)) {
            return getAccountListForPhone(baseVo, userId);
        }
        PageHelper.startPage(baseVo.getPageIndex(), baseVo.getPageSize());
        QueryWrapper<Account> wrapper = createWrapper();
        wrapper.like(Strings.isNotBlank(baseVo.getSearch()), "accountname", baseVo.getSearch());
        wrapper.eq(StringUtils.isNotBlank(baseVo.getColumnName())
                && StringUtils.isNotBlank(baseVo.getSelect()), baseVo.getColumnName(), baseVo.getSelect());
        orderByModifyTimeDesc(wrapper);
        List<Account> list = accountService.list(wrapper);
        if (CollectionUtil.isNotEmpty(list)) {
            return selectSuccess(list, list.size());
        }
        return selectNotFound(list, 0);
    }

    /**
     * 获取移动端用户的账户列表
     * @param baseVo
     * @param userId
     * @return
     */
    private JsonResult getAccountListForPhone(BaseVo baseVo, String userId) {
        QueryWrapper<Account> wrapper = createWrapperWithUserId(userId);
        List<AccountVo> accountVoList = accountService.selectListByPhone(baseVo, userId, wrapper);
        AccountResultVo accountResultVo = new AccountResultVo();
        if (CollectionUtil.isNotEmpty(accountVoList)) {
            List<AccountOtherVo> accountOtherVoList = new ArrayList<>();
            accountResultVo.setAccountOtherVoList(accountOtherVoList);
            // 根据类型分组，并统计全部的金额（总负债，净资产，总资产）
            Map<String, List<AccountVo>> typeAccountListMap = accountVoList.stream().collect(Collectors.groupingBy(Account::getType));
            for (String key : typeAccountListMap.keySet()) {
                AccountOtherVo accountOtherVo = new AccountOtherVo();
                accountOtherVo.setType(key);
                accountOtherVo.setName(Account.getTypeName(key));
                List<AccountVo> accountVoList1 = typeAccountListMap.get(key);
                BigDecimal money = accountVoList1.stream().map(AccountVo::getMoney).filter(ObjectUtil::isNotEmpty).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
                accountOtherVo.setMoney(money);
                accountOtherVo.setAccountVoList(accountVoList1);
                accountOtherVoList.add(accountOtherVo);
            }
            // 根据账户来计算出总负债，总资产，净资产
            accountResultVo.setNetAssets(accountOtherVoList.stream().flatMap(accountOtherVo -> accountOtherVo.getAccountVoList().stream()).map(AccountVo::getMoney).filter(money -> ObjectUtil.isNotEmpty(money) && BigDecimalUtil.biggerThen(money, BigDecimal.ZERO)).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
            accountResultVo.setTotalLiabilities(accountOtherVoList.stream().flatMap(accountOtherVo -> accountOtherVo.getAccountVoList().stream()).map(AccountVo::getMoney).filter(money -> ObjectUtil.isNotEmpty(money) && BigDecimalUtil.biggerThen(BigDecimal.ZERO, money)).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
            accountResultVo.setTotalAssets(accountResultVo.getNetAssets().add(accountResultVo.getTotalLiabilities()));

            // 查询账单信息
            List<String> accountIdList = accountVoList.stream().map(AccountVo::getId).collect(Collectors.toList());
            List<Bill> billList = billService.list(new BaseWrapper<Bill>().init(userId).in("account_id", accountIdList));
            Map<String, List<Bill>> accountIdBillListMap = billList.stream().collect(Collectors.groupingBy(Bill::getAccountId));
            if (CollectionUtil.isNotEmpty(accountIdBillListMap)) {
                for (AccountVo accountVo : accountVoList) {
                    List<Bill> bills = accountIdBillListMap.get(accountVo.getId());
                    if (CollectionUtil.isEmpty(bills)) {
                        continue;
                    }
                    // 根据天进行分组，然后统计每天的收入，支出金额
                    Map<String, List<Bill>> dayBillListMap = bills.stream().collect(Collectors.groupingBy(Bill::getDayTime));
                    if (CollectionUtil.isNotEmpty(dayBillListMap)) {
                        List<AccountBillVo> billVoList = new ArrayList<>();
                        for (String day : dayBillListMap.keySet()) {
                            AccountBillVo accountBillVo = new AccountBillVo();
                            accountBillVo.setDayTimeStr(day);
                            List<Bill> list = dayBillListMap.get(day);
                            accountBillVo.setDayForWeek(list.get(0).getWeekStr());
                            accountBillVo.setBillList(list);
                            // 根据类型分组
                            Map<String, List<Bill>> map = list.stream().collect(Collectors.groupingBy(Bill::getType));
                            if (CollectionUtil.isNotEmpty(map) && CollectionUtil.isNotEmpty(map.get(Constants.BILL_TYPE_PAY))) {
                                List<Bill> bills1 = map.get(Constants.BILL_TYPE_PAY);
                                accountBillVo.setPayMoney(bills1.stream().map(Bill::getMoney).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
                            }
                            if (CollectionUtil.isNotEmpty(map) && CollectionUtil.isNotEmpty(map.get(Constants.BILL_TYPE_INCOME))) {
                                List<Bill> bills1 = map.get(Constants.BILL_TYPE_INCOME);
                                accountBillVo.setPayMoney(bills1.stream().map(Bill::getMoney).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
                            }
                            billVoList.add(accountBillVo);
                        }
                        accountVo.setBillVoList(billVoList);
                    }
                    accountVo.setBillList(bills);
                }
            }
        }
        return JsonResult.selectSuccess(accountResultVo, 0);
    }

    @PutMapping
    @ApiOperation(value = "账户修改", notes = "路径参数传入账户对象")
    @OperateMethodName(value = "账户修改", method = "account:update")
    public JsonResult update(@RequestBody AccountVo accountVo){
        if (!Strings.isNotBlank(accountVo.getId())){
            return updateNotFound(accountVo, null);
        }

        accountService.updateAccount(accountVo);
        return updateSuccess(accountVo, null);
    }


    @PostMapping
    @ApiOperation(value = "添加账户", notes = "")
    @OperateMethodName(value = "添加账户", method = "account:insert")
    public JsonResult insert(@RequestBody AccountVo accountVO){
        Account account = accountService.saveAccount(accountVO);
        return insertSuccess(account, accountVO);
    }

    @DeleteMapping
    @ApiOperation(value = "删除", notes = "参数传入id")
    @OperateMethodName(value = "账户删除,批量", method = "account:delete")
    public JsonResult delete(String id){
        return delete(id, accountService, null);
    }
}
